//this class will read a file and pull data out
//this will also save data


//note rule file looks like
//id:string
//description: string
//genetic:string
//priortiy;num
//isActive:boolean

//id:string
package holdem.Rulegui;

//used for managing data in and out
import holdem.Emotion;
import holdem.ListInt;
import holdem.workingMemory.WorkingMemory;

import java.util.Random;
import java.util.Vector;
import java.io.*;//all of io
public class Loader implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 5357839983535702890L;
	private GeneticCode gencode;
	private Vector<Rule> ruleEmotion;
	private Vector<Rule> betting;
	private Vector<Object> keeper;
	transient private File f;
	public static void main(String[] j){
		Loader l = new Loader();
		ListIntDefualt d = new ListIntDefualt();
		ListIntDefualt a = new ListIntDefualt();
		ListIntDefualt c = new ListIntDefualt();
		ListIntDefualt e = new ListIntDefualt();
		ListIntDefualt b = new ListIntDefualt();
		a.add(b);
		a.add(c);
		b.add(d);
		c.add(e);
		e.set(2);
		d.set(3);
		testListInt(a);
		Loader gh = l.generate( a, l );
		Action ac= new Action();
		Emotion em = new Emotion();
		 gh.getBetRule().get(0).exicute(gh.gencode, a, ac);
		 gh.getRuleEm().get(0).exicute(gh.gencode, a, em);
		 for(int i =0; i < ac.size(); i++){
			System.out.println(ac.get(i).getSymbol());
		}
		 for(int i =0; i < em.size(); i++){
				System.out.println(em.get(i).getSymbol());
			}
	}
	public static void testListInt(ListInt l){
		if(l.isList()){
			for(int i = 0; i < l.getSize();i++){
				testListInt(l.get(i));
			}
		}
		if(l.isSymbol()){
			System.out.println(l.getSymbol());
		}
	}
	
	public Loader(File f){
		FileInputStream read = null;
		ObjectInputStream geter = null;
		Loader almostthis = null;
		this.f = f;
		try{
			read = new FileInputStream(f);
			geter = new ObjectInputStream(read);
			almostthis = (Loader) geter.readObject();
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("error Reading Rules");
			
		}
		gencode = almostthis.gencode;
		ruleEmotion = almostthis.ruleEmotion;
		betting = almostthis.betting;
	}
	public Loader() {
		// TODO Auto-generated constructor stub
	}
	public Vector<Rule> getRuleEm(){
		return ruleEmotion;
	}
	public void  setRulesEm(Vector<Rule> rule){
		this.ruleEmotion = rule;
	}
	public void  setRulesBet(Vector<Rule> rule){
		this.betting = rule;
	}
	public Vector<Rule> getBetRule(){
		return betting;
	}
	public void setGeneCode(GeneticCode code){
		this.gencode = code;		
	}
	public GeneticCode getCode(){
		return gencode;
	}
	public void save(File f){
		FileOutputStream out = null;
		ObjectOutputStream wr = null;
		try{
			out = new FileOutputStream(f);
			wr = new ObjectOutputStream(out);
			wr.writeObject(this);
		}catch( Exception e){
			e.printStackTrace();
		}
	}
	public void progenate(File[] list , double percent  ){
		for(int i = 0; i < list.length; i++){
			Loader l = new Loader(f);
			l.gencode.mutate(percent);
			l.save(list[i]);
		}
	}
	public Rule generateRulesEM(ListInt WM, ListInt playerEmotion, GeneticCode gene ,int depth,int actionsTaken) throws ExceptionNoData{
		Rule Rval = new Rule();
		Rval.setPrecondition(generateExpression(depth, WM, gene, Expression.operands));
		Rval.setEmotion(generateEmotion());
		Vector<ActionExpresion> vect = new Vector<ActionExpresion>();
		
		for(int i =0; i < actionsTaken; i++){
			Expression e = generateExpression(depth, WM, gene,"+:-".split(":"));
			Code c = generateTreeCode(playerEmotion);
			vect.add(new ActionExpresion(c,e));
		}
		Rval.setActionList(vect);
		return Rval;
	}
	public Rule generateRulesBet(ListInt WM, ListInt action, GeneticCode gene ,int depth) throws ExceptionNoData{
		Rule Rval = new Rule();
		Rval.setPrecondition(generateExpression(depth, WM, gene, Expression.operands ));
		Rval.setEmotion(generateEmotion());
		Vector<ActionExpresion> vect = new Vector<ActionExpresion>();
		
		for(int i =0; i < 1; i++){
			Expression e = generateExpression(depth, WM, gene, "+:-".split(":") );
			Code c = generateTreeCode(action);
			vect.add(new ActionExpresion(c,e));
		}
		Rval.setActionList(vect);
		return Rval;
	}
	public GeneCode generateGeneCode(GeneticCode gene){
		GeneCode code = new GeneCode(gene.size());
		Gene gen = new Gene(25, true);
		gene.add(gen);		
		return code;
	}
	public Emotion generateEmotion(){
			Random rand = new Random();
			Emotion Rval = new  Emotion();
			for(int i =0 ; i <  Rval.size(); i++){
				Rval.get(i).set(rand.nextInt(100));
			}
			return Rval;
	}
	public TreeCode generateTreeCode(ListInt WM)throws ExceptionNoData{
		//incase called form the top
		return generateTreeCode(WM, new Vector<Integer>());
	}
	public TreeCode generateTreeCode(ListInt WM, Vector<Integer> list)
	throws ExceptionNoData{
		//generartes TreeCode From a Wm
		
		//System.out.println(WM.getName());
		Random rand = new Random();
		if(WM.isSymbol()){
			return new TreeCode(list);
		}
		if(!WM.isSymbol() &&
				WM.getSize() == 0){//nothing there

			throw new ExceptionNoData();
		}
		
		// ! symbol -> ListInt
		//System.out.println(WM.getSize());
		int i = rand.nextInt( WM.getSize() );
		list.add(i);
		if(WM.get(i).isSymbol()){
			return new TreeCode(list);
		}
		return generateTreeCode(WM.get(i), list);	
	
	}
	public Expression generateExpression(int deep, ListInt WM, GeneticCode code, String[] operands) throws ExceptionNoData
	{
		Expression r =null;
		if( deep <=0){//bass case
			Expression Rval = new Expression();
			Expression left = new Expression();
			Expression right = new Expression();
			Rval.setOperand("+");
			Rval.setLeft(left);
			Rval.setRight(right);
			
			left.setLeaf(generateTreeCode(WM));
			
			right.setLeaf(generateGeneCode(code));
			
			
			return Rval;
		}
		Random random = new Random();
		Expression rval = new Expression();
		rval.setLeft(generateExpression(deep/2, WM, code,operands));
		rval.setRight(generateExpression(deep/2, WM, code,operands));
		rval.setOperand(operands[random.nextInt(operands.length)]);
		return rval;
	}
	public void prune(Vector<Rule> list ,int Low){
		for(int i = 0; i < list.size(); i++){
			if(list.get(i).NumberCAlled() < Low){
				list.remove(i--);
			}
		}
	}
	public void prune(int i){
		prune(ruleEmotion, i);
		prune(betting, i);
	}
	public Loader generate(ListInt WM, Loader l) {
		
		l.gencode = new GeneticCode();
		ListInt Em = new Emotion();
		ListInt Act = new Action();
		Vector<Rule> v = new Vector<Rule>();
		for(int i = 0; i < 20; i++){
			try{
			v.add(generateRulesBet(WM, Act, l.gencode , 4));
			}catch(ExceptionNoData e){
				i--;//reroll
			}
		}
		l.betting = v;
		v = new Vector<Rule>();
		for(int i = 0; i < 20; i++){
			try{
			v.add( generateRulesEM(WM, Em, l.gencode, 4, 4));
			//System.out.println("======================================");
			}catch(ExceptionNoData e){
				i--;//reroll
			}
		}
		l.ruleEmotion = v;
		return l;
	}
}
